package com.lineage.server.model.Instance;

import com.lineage.server.IdFactoryNpc;
import com.lineage.server.datatables.ItemTable;
import com.lineage.server.model.L1AttackPc;
import com.lineage.server.model.L1Character;
import com.lineage.server.model.L1Object;
import com.lineage.server.serverpackets.S_DoActionGFX;
import com.lineage.server.serverpackets.S_FollowerPack;
import com.lineage.server.serverpackets.S_NPCTalkReturn;
import com.lineage.server.serverpackets.S_ServerMessage;
import com.lineage.server.serverpackets.ServerBasePacket;
import com.lineage.server.templates.L1Npc;
import com.lineage.server.thread.GeneralThreadPool;
import com.lineage.server.types.Point;
import com.lineage.server.utils.L1SpawnUtil;
import com.lineage.server.world.World;
import java.util.Iterator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class L1FollowerInstance extends L1NpcInstance {
  private static final long serialVersionUID = 1L;
  
  private static final Log _log = LogFactory.getLog(L1FollowerInstance.class);
  
  public boolean noTarget() {
    if (this.ATTACK != null) {
      L1PcInstance pc = null;
      if (this._master instanceof L1PcInstance)
        pc = (L1PcInstance)this._master; 
      this.ATTACK.attack(pc, this);
    } else {
      Iterator<L1Object> iterator = World.get().getVisibleObjects((L1Object)this).iterator();
      while (iterator.hasNext()) {
        L1Object object = iterator.next();
        if (object instanceof L1NpcInstance) {
          L1NpcInstance tgnpc = (L1NpcInstance)object;
          if (tgnpc.getNpcTemplate().get_npcId() == 71061 && getNpcTemplate().get_npcId() == 71062) {
            if (getLocation().getTileLineDistance((Point)this._master.getLocation()) >= 3)
              continue; 
            L1PcInstance l1PcInstance = (L1PcInstance)this._master;
            if (l1PcInstance.getX() < 32448 || l1PcInstance.getX() > 32452 || l1PcInstance.getY() < 33048 || l1PcInstance.getY() > 33052)
              continue; 
            if (l1PcInstance.getMapId() != 440)
              continue; 
            setParalyzed(true);
            if (!l1PcInstance.getInventory().checkItem(40711)) {
              createNewItem(l1PcInstance, 40711, 1L);
              l1PcInstance.getQuest().set_step(31, 3);
            } 
            deleteMe();
            return true;
          } 
          if (tgnpc.getNpcTemplate().get_npcId() != 71074 || getNpcTemplate().get_npcId() != 71075 || 
            getLocation().getTileLineDistance((Point)this._master.getLocation()) >= 3)
            continue; 
          L1PcInstance pc2 = (L1PcInstance)this._master;
          if (pc2.getX() >= 32731 && pc2.getX() <= 32735 && pc2.getY() >= 32854 && pc2.getY() <= 32858 && 
            pc2.getMapId() == 480) {
            setParalyzed(true);
            if (!pc2.getInventory().checkItem(40633)) {
              createNewItem(pc2, 40633, 1L);
              pc2.getQuest().set_step(34, 2);
            } 
            deleteMe();
            return true;
          } 
        } 
      } 
    } 
    if (destroyed())
      return true; 
    if (this._master == null)
      return true; 
    if (this._master.isDead() || getLocation().getTileLineDistance((Point)this._master.getLocation()) > 13) {
      setParalyzed(true);
      spawn(getNpcTemplate().get_npcId(), getX(), getY(), getHeading(), getMapId());
      deleteMe();
      return true;
    } 
    if (this._master != null && this._master.getMapId() == getMapId() && 
      getLocation().getTileLineDistance((Point)this._master.getLocation()) > 2 && this._npcMove != null) {
      this._npcMove.setDirectionMove(this._npcMove.moveDirection(this._master.getX(), this._master.getY()));
      setSleepTime(calcSleepTime(getPassispeed(), 0));
    } 
    return false;
  }
  
  public L1FollowerInstance(L1Npc template, L1NpcInstance target, L1Character master) {
    super(template);
    if (is(master))
      return; 
    this._master = master;
    setId(IdFactoryNpc.get().nextId());
    set_showId(master.get_showId());
    setMaster(master);
    setX(target.getX());
    setY(target.getY());
    setMap(target.getMapId());
    setHeading(target.getHeading());
    setLightSize(target.getLightSize());
    target.setParalyzed(true);
    target.deleteMe();
    World.get().storeObject((L1Object)this);
    World.get().addVisibleObject((L1Object)this);
    Iterator<L1PcInstance> iterator = World.get().getRecognizePlayer((L1Object)this).iterator();
    while (iterator.hasNext()) {
      L1PcInstance pc = iterator.next();
      onPerceive(pc);
    } 
    onNpcAI();
    master.addFollower(this);
  }
  
  private boolean is(L1Character master) {
    return (master.getFollowerList().size() > 0);
  }
  
  public void onNpcAI() {
    if (isAiRunning())
      return; 
    startAI();
  }
  
  public synchronized void deleteMe() {
    this._master.removeFollower(this);
    setMaster((L1Character)null);
    getMap().setPassable((Point)getLocation(), true);
    super.deleteMe();
  }
  
  public void onAction(L1PcInstance pc) {
    try {
      L1AttackPc l1AttackPc = new L1AttackPc(pc, this);
      if (l1AttackPc.calcHit()) {
        l1AttackPc.calcDamage();
        l1AttackPc.calcStaffOfMana();
      } 
      l1AttackPc.action();
      l1AttackPc.commit();
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
    } 
  }
  
  public void onTalkAction(L1PcInstance player) {
    if (isDead())
      return; 
    switch (getNpcTemplate().get_npcId()) {
      case 71062:
        if (this._master.equals(player)) {
          player.sendPackets((ServerBasePacket)new S_NPCTalkReturn(getId(), "kamit2"));
          break;
        } 
        player.sendPackets((ServerBasePacket)new S_NPCTalkReturn(getId(), "kamit1"));
        break;
      case 71075:
        if (this._master.equals(player)) {
          player.sendPackets((ServerBasePacket)new S_NPCTalkReturn(getId(), "llizard2"));
          break;
        } 
        player.sendPackets((ServerBasePacket)new S_NPCTalkReturn(getId(), "llizard1a"));
        break;
    } 
  }
  
  public void onPerceive(L1PcInstance perceivedFrom) {
    try {
      if (perceivedFrom.get_showId() != get_showId())
        return; 
      perceivedFrom.addKnownObject((L1Object)this);
      perceivedFrom.sendPackets((ServerBasePacket)new S_FollowerPack(this, perceivedFrom));
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
    } 
  }
  
  private void createNewItem(L1PcInstance pc, int item_id, long count) {
    L1ItemInstance item = ItemTable.get().createItem(item_id);
    item.setCount(count);
    if (item != null) {
      if (pc.getInventory().checkAddItem(item, count) == 0) {
        pc.getInventory().storeItem(item);
      } else {
        item.set_showId(pc.get_showId());
        World.get().getInventory(pc.getX(), pc.getY(), pc.getMapId()).storeItem(item);
      } 
      pc.sendPackets((ServerBasePacket)new S_ServerMessage(403, item.getLogName()));
    } 
  }
  
  public void spawn(int npcId, int x, int y, int h, short m) {
    try {
      L1NpcInstance mob = L1SpawnUtil.spawn(npcId, x, y, m, h);
      L1QuestInstance newnpc = (L1QuestInstance)mob;
      newnpc.onNpcAI();
      newnpc.startChat(0);
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
    } 
  }
  
  public void receiveDamage(L1Character attacker, int damage) {
    if (getMaxHp() > 100)
      if (getCurrentHp() > 0 && !isDead()) {
        int newHp = getCurrentHp() - damage;
        if (newHp <= 0 && !isDead()) {
          setCurrentHpDirect(0);
          setDead(true);
          setStatus(8);
          Death death = new Death();
          GeneralThreadPool.get().execute(death);
        } 
        if (newHp > 0)
          setCurrentHp(newHp); 
      } else if (!isDead()) {
        setDead(true);
        setStatus(8);
        Death death2 = new Death();
        GeneralThreadPool.get().execute(death2);
      }  
  }
  
  private class Death implements Runnable {
    private Death() {}
    
    public void run() {
      try {
        L1FollowerInstance.this.getMap().setPassable((Point)L1FollowerInstance.this.getLocation(), true);
        L1FollowerInstance.this.setDeathProcessing(true);
        L1FollowerInstance.this.broadcastPacketAll((ServerBasePacket)new S_DoActionGFX(L1FollowerInstance.this.getId(), 8));
        L1FollowerInstance.this.setDeathProcessing(false);
        L1FollowerInstance.this.startDeleteTimer(10);
      } catch (Exception e) {
        L1FollowerInstance._log.error(e.getLocalizedMessage(), e);
      } 
    }
  }
}
